﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Data.Objects.DataClasses;
using System.Data;
using Ditto.Helpers;

namespace Ditto.Models
{

    public class ItemRepository : Ditto.Models.IItemRepository
    {

        DittoEntities db = new DittoEntities();

        //
        // Query Methods

        public IQueryable<Item> FindItemsByText(string q)
        {
            return db.Items.Where(d => d.Title.Contains(q)
                            || d.Description.Contains(q)
                            || d.PostingUserID.Contains(q));
        }

        public IQueryable<Item> FindAllItems()
        {
            return db.Items;
        }

        public IQueryable<Item> FindUpcomingItems()
        {
            return from item in FindAllItems()
                   //where item.EventDate >= DateTime.Now
                   orderby item.TimeCreated descending
                   select item;
        }

        public IQueryable<Item> FindByLocation(float latitude, float longitude)
        {
            var items = from item in FindUpcomingItems()
                          join i in NearestItems(latitude, longitude)
                          on item.ItemID equals i.ItemID
                          select item;

            return items;
        }

        public IQueryable<Item> FindByUser(string userID)
        {
            return db.Items.Where(i => i.PostingUserID == userID);
        }

        public IQueryable<Item> FindItemsRequested(string userID)
        {
            var requested = from r in db.Requests.Include("Item")
                            where r.Item.PostingUserID == userID
                            select r.Item;

            return requested;
        }

        public IQueryable<Item> FindItemsRequesting(string userID)
        {
            var requesting = from r in db.Requests.Include("Item")
                            where r.RequestingUserID == userID
                            select r.Item;

            return requesting;
        }

        public IQueryable<Request> FindRequestingUsers(int itemID)
        {
            var users = from r in db.Requests.Include("User").Include("Item")
                        where r.ItemID == itemID
                        select r;

            return users;
        }

        public Request FindRequest(int itemID, string requestingUserID) 
        {
            return db.Requests.Include("User").Include("Item").SingleOrDefault(r => r.ItemID == itemID && r.RequestingUserID == requestingUserID);
        }

        public void Add(Request request) 
        {
            db.Requests.AddObject(request);
        }

        public void Delete(Request request) 
        {
            db.DeleteObject(request);
        }


        public Request GetRequest(int requestID)
        {
            return db.Requests.Include("User").Include("Items").SingleOrDefault(d => d.RequestID == requestID);
        }

        public Transaction FindTransaction(int itemID)
        {
            return db.Transactions.FirstOrDefault(t => t.ItemID == itemID);
        }


        public Item GetItem(int id)
        {
            return db.Items.SingleOrDefault(d => d.ItemID == id);
        }

        //
        // Insert/Delete Methods

        public void Add(Item item)
        {
            db.Items.AddObject(item);
        }

        public void Delete(Item item)
        {
            //foreach (RSVP rsvp in item.RSVPs.ToList())
            //    db.RSVPs.DeleteObject(rsvp);
            db.Items.DeleteObject(item);
        }

        //
        // Persistence 

        public void Save()
        {
            db.SaveChanges();
        }

        [EdmFunction("Ditto.Store", "DistanceBetween")]
        public static double DistanceBetween(double lat1, double long1, double lat2, double long2)
        {
            GeolocationHelper.Coordinate from = new GeolocationHelper.Coordinate(long1, lat1);
            GeolocationHelper.Coordinate to = new GeolocationHelper.Coordinate(long2, lat2);
            GeolocationHelper.DistTime dist = GeolocationHelper.DistTime.GetStraightLineDistTime(from, to);

            return dist.Distance;
        }

        //[EdmFunction("Ditto.Models.Store", "NearestItems")]
        public IQueryable<Item> NearestItems(double latitude, double longitude)
        {
            return from d in db.Items
                   where DistanceBetween(latitude, longitude, d.Latitude, d.Longitude) < 100
                   select d;
        }
    }
}
